/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.ufg.inf.si.poo.formula1.Simulator;

import br.ufg.inf.si.poo.formula1.Library.Library;
import br.ufg.inf.si.poo.formula1.Race.GridPosition;
import br.ufg.inf.si.poo.formula1.Race.Qualification;

/**
 * SimulatorQualification
 * 
 * Versao 1.0
 * 
 * Data 26/01/2013
 * 
 * @author Igor
 */
public class SimulatorQualification {
    //Construtores
    private SimulatorQualification(){}

    //Outros Metodos
    /**
     * Gera tempos para todos os pilotos participantes da qualificação
     * @param qualification, gera valores de Q1 para a qualificação Gera valores
     * de Q1 para todos os pilotos
     */
    private static void generateQ1(Qualification qualification) {
        for (int i = 0; i < qualification.getQttDrivers(); i++) {
            //Gera aleatoriamente quantas voltas o pilotos executara
            int qttLapsDriver = Library.generatesLaps();

            qualification.getQualification()[i].setQ1(genarateLessTime(qttLapsDriver));
            qualification.getQualification()[i].setQttLapsQualification(qualification.getQualification()[i].getQttLapsQualification() + qttLapsDriver);
        }
        SimulatorQualification.orderDriversAfterQ1(qualification);
    }

    /**
     * Ordena todo o vetor de qualificação de acordo com o tempo Q1 e valida
     * os pilotos que obtiveram tempo superior a 107% do menor tempo
     * @param qualification, qualificação para ser ordenada Gera valores de Q1
     * para todos os pilotos
     */
    private static void orderDriversAfterQ1(Qualification qualification) {
        for (int i = 0; i < qualification.getQttDrivers() - 1; i++) {
            for (int j = i + 1; j < qualification.getQttDrivers(); j++) {
                if (qualification.getQualification()[i].getQ1() > qualification.getQualification()[j].getQ1()) {
                    GridPosition gridPosition = qualification.getQualification()[i];
                    qualification.getQualification()[i] = qualification.getQualification()[j];
                    qualification.getQualification()[j] = gridPosition;
                }
            }
        }

        /* Verifique se houve pilotos com mais de 107% do menor tempo */
        if (qualification.getQualification()[0] != null) {
            long lessTime = qualification.getQualification()[0].getQ1();
            for (int i = 1; i < qualification.getQttDrivers(); i++) {
                if ((lessTime * 1.07) < qualification.getQualification()[i].getQ1()) {
                    qualification.getQualification()[i].setStatus("DNQ");
                }
            }
        }
    }

    /**
     * Gera tempos para os pilotos que estao classificados para Q2
     * @param qualification, gera valores de Q2 para a qualificação Gera valores
     * de Q2 para todos os pilotos
     */
    private static void generateQ2(Qualification qualification) {
        if (qualification.getQttDrivers() - 10 >= 0) {
            for (int i = 0; i < (qualification.getQttDrivers() - 8); i++) {
                //Gera aleatoriamente quantas voltas o pilotos executará
                int qttLapsDriver = Library.generatesLaps();
 
               qualification.getQualification()[i].setQ2(genarateLessTime(qttLapsDriver));
                qualification.getQualification()[i].setQttLapsQualification(qualification.getQualification()[i].getQttLapsQualification() + qttLapsDriver);
            }
        }
        SimulatorQualification.orderDriversAfterQ2(qualification);
    }

    /**
     * Ordena o vetor de qualificação, de acordo com as regras de Q2, ou seja,
     * apenas os que passaram em Q1
     * @param qualification, qualificação para ser ordenada Gera valores de Q2
     * para todos os pilotos
     */
    private static void orderDriversAfterQ2(Qualification qualification) {
        for (int i = 0; i < (qualification.getQttDrivers() - 1 - 8); i++) {
            for (int j = i + 1; j < (qualification.getQttDrivers() - 8); j++) {
                if (qualification.getQualification()[i].getQ2() > qualification.getQualification()[j].getQ2()) {
                    GridPosition gridPosition = qualification.getQualification()[i];
                    qualification.getQualification()[i] = qualification.getQualification()[j];
                    qualification.getQualification()[j] = gridPosition;
                }
            }
        }
    }

    /**
     * Gera tempos para os pilotos que estão classificados para Q3
     * @param qualification, gera valores de Q3 para a qualificação Gera valores
     * de Q3 para todos os pilotos
     */
    private static void generateQ3(Qualification qualification) {
        for (int i = 0; i < 10; i++) {
            //Gera aleatoriamente quantas voltas o pilotos executará
            int qttLapsDriver = Library.generatesLaps();
            if(qualification.getQualification()[i] != null){
                qualification.getQualification()[i].setQ3(genarateLessTime(qttLapsDriver));
                qualification.getQualification()[i].setQttLapsQualification(qualification.getQualification()[i].getQttLapsQualification() + qttLapsDriver);
            }
        }
        SimulatorQualification.orderDriversAfterQ3(qualification);
    }

    /**
     * Ordena o vetor de qualificação, de acordo com as regras de Q3, ou seja,
     * apenas os 10 primeiros serão ordenados
     * @param qualification, qualificação para ser ordenada Gera valores de Q3
     * para todos os pilotos
     */
    private static void orderDriversAfterQ3(Qualification qualification) {
        for (int i = 0; i < 10 - 1; i++) {
            for (int j = i + 1; j < 10; j++) {
                if(qualification.getQualification()[i] != null){
                    if (qualification.getQualification()[i].getQ3() > qualification.getQualification()[j].getQ3()) {
                        GridPosition gridPosition = qualification.getQualification()[i];
                        qualification.getQualification()[i] = qualification.getQualification()[j];
                        qualification.getQualification()[j] = gridPosition;
                    }
                }
            }
        }
        
        for (int i = 0; i < qualification.getQttDrivers(); i++) {
            if(qualification.getQualification()[i] != null){
                qualification.getQualification()[i].setPosition(i+1);
            }
        }
    }
    
    /**
     * Gera X tempos aleatrorios, sendo X a quantidade de voltas que o piloto executará
     * retornando o menor tempo gerado
     * @param qttLapsDriver, quantidade de voltas que o piloto executará
     * @return 
     */
    private static long genarateLessTime(int qttLapsDriver){
        long lessTimeLap = 80000; //80000 é o maior número que o generatesTime pode gerar
        for (int j = 0; j < qttLapsDriver; j++) {
            long timeLap = Library.generatesTime();
            if (timeLap < lessTimeLap) {
                lessTimeLap = timeLap;
            }
        }
        return lessTimeLap;
    }
    
    /**
     * Executa os metodos que geram os dados para qualificação
     * @param qualification, qualificação que será gerado os dados
     */
    public static void exercuteQualification(Qualification qualification){
        SimulatorQualification.generateQ1(qualification);
        SimulatorQualification.generateQ2(qualification);
        SimulatorQualification.generateQ3(qualification);
    }
}
